﻿// -----------------------------------------------------------------------
// <copyright file="ImageGeometry.cs" company="Microsoft">
// Created 22/10/2011
// </copyright>
// -----------------------------------------------------------------------

namespace ImageProcessing
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using ImageProcessing.IntermediateClasses;
    using ImageProcessing.Utilities;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class ImageGeometry
    {
        /// <summary>
        /// Resizes the image using Bilinear interpolation
        /// </summary>
        /// <param name="image">Current image in picture box</param>
        /// <param name="targetWidth">Target Width</param>
        /// <param name="targetHeight">Target Height</param>
        /// <returns>Bitmap image</returns>
        public Bitmap BilinearResize(Image image, int targetWidth, int targetHeight)
        {
            try
            {
                Bitmap originalImage = new Bitmap(image);
                Colour.ColorsStruct[,] tempImage = Colour.ConvertToStruct(originalImage);
                int originalHeight = originalImage.Height;
                int originalWidth = originalImage.Width;

                float sourceX, sourceY, xFraction, yFraction, z1Red, z1Green, z1Blue, z2Red, z2Green, z2Blue;
                int x1, x2, y1, y2, newPixelRed, newPixelGreen, newPixelBlue;

                Bitmap resizedImage = new Bitmap(targetWidth, targetHeight);

                float widthRatio = (float)originalWidth / targetWidth;
                float heightRatio = (float)originalHeight / targetHeight;

                for (int i = 0; i < targetWidth; i++)
                {
                    for (int j = 0; j < targetHeight; j++)
                    {
                        sourceX = i * widthRatio;
                        sourceY = j * heightRatio;

                        x1 = (int)sourceX;
                        x2 = x1 + 1;
                        y1 = (int)sourceY;
                        y2 = y1 + 1;

                        if (x2 >= originalWidth)
                        {
                            x2 = x1;
                        }

                        if (y2 >= originalHeight)
                        {
                            y2 = y1;
                        }

                        xFraction = sourceX - x1;
                        yFraction = sourceY - y1;

                        z1Red = (tempImage[x1, y1].Red * (1 - xFraction)) + (tempImage[x2, y1].Red * xFraction);
                        z1Green = (tempImage[x1, y1].Green * (1 - xFraction)) + (tempImage[x2, y1].Green * xFraction);
                        z1Blue = (tempImage[x1, y1].Blue * (1 - xFraction)) + (tempImage[x2, y1].Blue * xFraction);

                        //z1Red = (originalImage.GetPixel(x1, y1).R * (1 - xFraction)) + (originalImage.GetPixel(x2, y1).R * xFraction);
                        //z1Green = (originalImage.GetPixel(x1, y1).G * (1 - xFraction)) + (originalImage.GetPixel(x2, y1).G * xFraction);
                        //z1Blue = (originalImage.GetPixel(x1, y1).B * (1 - xFraction)) + (originalImage.GetPixel(x2, y1).B * xFraction);

                        z2Red = (tempImage[x1, y2].Red * (1 - xFraction)) + (tempImage[x2, y2].Red * xFraction);
                        z2Green = (tempImage[x1, y2].Green * (1 - xFraction)) + (tempImage[x2, y2].Green * xFraction);
                        z2Blue = (tempImage[x1, y2].Blue * (1 - xFraction)) + (tempImage[x2, y2].Blue * xFraction);

                        //z2Red = (originalImage.GetPixel(x1, y2).R * (1 - xFraction)) + (originalImage.GetPixel(x2, y2).R * xFraction);
                        //z2Green = (originalImage.GetPixel(x1, y2).G * (1 - xFraction)) + (originalImage.GetPixel(x2, y2).G * xFraction);
                        //z2Blue = (originalImage.GetPixel(x1, y2).B * (1 - xFraction)) + (originalImage.GetPixel(x2, y2).B * xFraction);

                        newPixelRed = (int)((z1Red * (1 - yFraction)) + (z2Red * yFraction));
                        newPixelGreen = (int)((z1Green * (1 - yFraction)) + (z2Green * yFraction));
                        newPixelBlue = (int)((z1Blue * (1 - yFraction)) + (z2Blue * yFraction));

                        resizedImage.SetPixel(i, j, Color.FromArgb(newPixelRed, newPixelGreen, newPixelBlue));
                    }
                }

                return resizedImage;
            }
            catch (Exception e)
            {
                Logger.LogException(e);
                throw;
            }
        }

        /// <summary>
        /// Translates image by offset in x and y direction
        /// </summary>
        /// <param name="image">Currently displayed image</param>
        /// <param name="xOffset">Offset in x direction</param>
        /// <param name="yOffset">Offset in y direction</param>
        /// <returns>Bitmap image</returns>
        public Bitmap Translate(Image image, int xOffset, int yOffset)
        {
            try
            {
                Bitmap originalImage = new Bitmap(image);
                int width = image.Width + xOffset;
                int heigth = image.Height + yOffset;
                Bitmap newImage = new Bitmap(width, heigth);
                for (int j = 0; j < image.Height; j++)
                {
                    for (int i = 0; i < image.Width; i++)
                    {
                        newImage.SetPixel(i + xOffset, j + yOffset, Color.FromArgb(originalImage.GetPixel(i, j).R, originalImage.GetPixel(i, j).G, originalImage.GetPixel(i, j).B));
                    }
                }

                return newImage;
            }
            catch (Exception e)
            {
                Logger.LogException(e);
                throw;
            }
        }

        /// <summary>
        /// Rotates image clockwise/anticlockwise
        /// </summary>
        /// <param name="image">Currently displayed image</param>
        /// <param name="clockwise">Image rotation direction</param>
        /// <returns>Bitmap image</returns>
        public Bitmap Rotate(Image image, bool clockwise)
        {
            try
            {
                Bitmap originalImage = new Bitmap(image);
                int width = image.Width;
                int heigth = image.Height;
                Bitmap newImage = new Bitmap(heigth, width);
                if (clockwise)
                {
                    for (int i = 0; i < heigth; i++)
                    {
                        for (int j = 0; j < width; j++)
                        {
                            newImage.SetPixel((heigth - 1 - i), j, Color.FromArgb(originalImage.GetPixel(j, i).R, originalImage.GetPixel(j, i).G, originalImage.GetPixel(j, i).B));
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < heigth; i++)
                    {
                        for (int j = 0; j < width; j++)
                        {
                            newImage.SetPixel(i, (width - 1 - j), Color.FromArgb(originalImage.GetPixel(j, i).R, originalImage.GetPixel(j, i).G, originalImage.GetPixel(j, i).B));
                        }
                    }
                }

                return newImage;
            }
            catch (Exception e)
            {
                Logger.LogException(e);
                throw;
            }
        }

        ////public Bitmap RotateSpecificAngle(Image image, bool clockwise, double rotationAngle)
        ////{
        ////    try
        ////    {
        ////        Bitmap originalImage = new Bitmap(image);
        ////        int width = (int)Math.Abs(image.Width * Math.Cos(rotationAngle) + image.Height * Math.Sin(rotationAngle));
        ////        int heigth = (int)Math.Abs(image.Height * Math.Cos(rotationAngle) - image.Width * Math.Sin(rotationAngle));
        ////        Bitmap newImage = new Bitmap(width, heigth);
        ////        if (clockwise)
        ////        {
        ////            for (int i = 0; i < heigth; i++)
        ////            {
        ////                for (int j = 0; j < width; j++)
        ////                {
        ////                    newImage.SetPixel((int)(j * Math.Cos(rotationAngle) + i * Math.Sin(rotationAngle)), (int)(i * Math.Cos(rotationAngle) - j * Math.Sin(rotationAngle)), Color.FromArgb(originalImage.GetPixel(j, i).R, originalImage.GetPixel(j, i).G, originalImage.GetPixel(j, i).B));
        ////                }
        ////            }
        ////        }
        ////        else
        ////        {
        ////            for (int i = 0; i < heigth; i++)
        ////            {
        ////                for (int j = 0; j < width; j++)
        ////                {
        ////                    newImage.SetPixel((int)(j * Math.Cos(-rotationAngle) + i * Math.Sin(-rotationAngle)), (int)(i * Math.Cos(-rotationAngle) - j * Math.Sin(-rotationAngle)), Color.FromArgb(originalImage.GetPixel(j, i).R, originalImage.GetPixel(j, i).G, originalImage.GetPixel(j, i).B));
        ////                }
        ////            }
        ////        }

        ////        return newImage;
        ////    }
        ////    catch (Exception e)
        ////    {
        ////        Logger.LogException(e);
        ////        throw;
        ////    }
        ////}
    }
}
